package com.yg.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yg.config.FilePathConfig;
import com.yg.config.exceptionhandler.YGException;
import com.yg.config.result.R;
import com.yg.config.result.ResultCode;
import com.yg.entity.readAndWriteTemplates.TeacherRead;
import com.yg.entity.singleEntity.Dictionary;
import com.yg.entity.singleEntity.Teacher;
import com.yg.entity.singleEntity.TeacherEducation;
import com.yg.mapper.DictionaryMapper;
import com.yg.mapper.TeacherEducationMapper;
import com.yg.mapper.TeacherMapper;
import com.yg.service.TeacherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yg.utils.JwtUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 对应sheet01和其他表，此表为教师表 服务实现类
 * </p>
 *
 * @author YingGu
 * @since 2020-11-04
 */
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {

    @Autowired
    TeacherMapper teacherMapper;
    @Autowired
    TeacherEducationMapper teacherEducationMapper;
    @Autowired
    DictionaryMapper dictionaryMapper;
    @Autowired
    FilePathConfig filePathConfig;

    @Override
    public R teacherLogin(Teacher teacher) {
        //从前端获得用户名和密码
        String teacherId = teacher.getTeacherId();
        String password = teacher.getPassword();

        QueryWrapper<Teacher> wrapper = new QueryWrapper<>();
        wrapper.eq("teacher_id", teacherId);
        Teacher one = baseMapper.selectOne(wrapper);

        //假如返回一个null，说明用户不存在
        if (one != null) {
            //假如密码相同，则登陆成功。失败则返回失败状态码
            if (DigestUtils.md5DigestAsHex(DigestUtils.md5Digest(password.getBytes())).equals(one.getPassword())) {
                System.out.println("token-------------------" + JwtUtils.getJwtToken(one.getId(), one.getTeacherId(),one.getVip()));
                return R.OK().code(ResultCode.LOGINSUCCESS).message("登录成功").data("token", JwtUtils.getJwtToken(one.getId(), one.getTeacherId(),one.getVip())).data("role", one.getVip());
            } else {
                return R.ERROR().code(ResultCode.USERPASSWORDERROR);
            }
        } else {
            return R.ERROR().code(ResultCode.USERDOESNOTEXIST);
        }
    }

    /**
     * excel写入
     * @return
     */
    @Transactional
    @Override
    public R readExcel(FileInputStream fileInputStream) {
        //创建要录入的bean的list
        List<Teacher> teacherList = new ArrayList<>();
        List<TeacherEducation> teacherEducationList = new ArrayList<>();
        //创建R
        R r = R.getR();
        r.setCode(ResultCode.SUCCESS);
        //存储错误信息
        List<String> errorList = new ArrayList<>();

        //读取excel(匿名内部类解决传参问题)
        EasyExcel.read(fileInputStream, TeacherRead.class, new AnalysisEventListener<TeacherRead>() {

            @Override
            public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
                System.out.println(headMap.toString());
            }

            //每行执行
            @Override
            public void invoke(TeacherRead teacherRead, AnalysisContext analysisContext) {
                //创建数据库对应实体类
                Teacher teacher = new Teacher();
                TeacherEducation teacherEducation = new TeacherEducation();

                //将表格bean复制到对应数据库bean
                BeanUtils.copyProperties(teacherRead,teacher);
                BeanUtils.copyProperties(teacherRead,teacherEducation);

                //添加进list
                teacherList.add(teacher);
                teacherEducationList.add(teacherEducation);
            }

            //所有行读完执行
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                if (r.getCode() == ResultCode.SUCCESS){
                    //向数据库插入数据
                    saveData();
                }else {
                    //添加错误信息
                    r.data("errorMsg",errorList);
                }
            }


            /**
             * 数据类型转换异常处理
             * @param exception
             * @param context
             * @throws Exception
             */
            @Override
            public void onException(Exception exception, AnalysisContext context) throws Exception {
                if (exception instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;

                    //向errorList中添加信息
                    r.code(ResultCode.ERROR);
                    System.out.println("行："+excelDataConvertException.getRowIndex() + "列" +excelDataConvertException.getColumnIndex());
                    errorList.add("行："+excelDataConvertException.getRowIndex() + "列" +excelDataConvertException.getColumnIndex());
//                    LOGGER.error("第{}行，第{}列解析异常", excelDataConvertException.getRowIndex(),
//                            excelDataConvertException.getColumnIndex());
                }
            }

            //存数据库操作
            private void saveData(){
                for (int i = 0; i < teacherList.size(); i++) {
                    try {
                        teacherMapper.insert(teacherList.get(i));
                    } catch (RuntimeException e) {
                        //i+5是表的第五行开始(显示报错行数)
                        throw new YGException(ResultCode.INSERTERROR,e.getCause().getMessage(),i + 5);
                    }
                }

                for (int i = 0; i < teacherEducationList.size(); i++) {
                    //teacher表赋值给teacherEducation
                    teacherEducationList.get(i).setId(teacherList.get(i).getId());
                    teacherEducationMapper.insert(teacherEducationList.get(i));
                }

                //r中写入成功信息
                r.code(ResultCode.SUCCESS).message("插入成功");
            }
        }).headRowNumber(4).sheet().doRead();

        return r;
    }


    /**
     * excel写出
     * @return
     */
    @Transactional
    @Override
    public R writeExcel(HttpServletResponse response ,TeacherRead teacherRead,String vipByJwtToken,String teacherIdByJwtToken) {
        //从数据库中查询对应表格
        List<Teacher> teachers = teacherMapper.selectList(null);
        List<TeacherEducation> teacherEducations = teacherEducationMapper.selectList(null);
        List<TeacherRead> teacherReadList = teacherMapper.writeTeacherConditionalQuery(teacherRead,vipByJwtToken,teacherIdByJwtToken);

        //将数据库对应的bean复制给导出表格bean
        for (int i = 0; i < teacherReadList.size(); i++) { //复制teacher中的属性
            //设置序号
            teacherReadList.get(i).setNum(i + 1);
        }

        //导出(匿名内部类SheetWriteHandler)
        response.addHeader("Content-Disposition", "attachment;fileName=下载案例1.xlsx");// 设置文件名
        try {
            EasyExcel.write(response.getOutputStream()).withTemplate(filePathConfig.writeExcelFilePath + "sheet01Template.xlsx").registerWriteHandler(new SheetWriteHandler() {

                @Override
                public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

                }

                @Override
                public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
                    //日志
                }


            }).sheet().doFill(teacherReadList);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return R.OK();
    }

    /**
     * 查询教师所有信息
     * @return
     */
    @Override
    public R selectAllTeacherInfo(int current,int limit,String vipByJwtToken,String teacherIdByJwtToken) {
        //Page类的构造函数中第一个参数为当前查询第几页，第二个参数为每页的记录数(分页查询)
        Page<TeacherRead> teacherReadPage = new Page<TeacherRead>(current,limit);
        IPage<TeacherRead> teacherReadIPage = teacherMapper.selectAllTeacherInfo(teacherReadPage,vipByJwtToken,teacherIdByJwtToken);
        List<TeacherRead> records = teacherReadIPage.getRecords();

        for (TeacherRead record : records) {
            if (record.getBirthday() != null && record.getWorkTime() != null){
                //计算年龄
                record.setAge(Calendar.getInstance().get(Calendar.YEAR) - Integer.valueOf(record.getBirthday().substring(0,4)));
                record.setSeniority(Calendar.getInstance().get(Calendar.YEAR) - Integer.valueOf(record.getWorkTime().substring(0,4)));
            }
        }

        //获取字典表
        Map<String, List<Dictionary>> dictionary = this.getDictionary();
        return R.OK().data("list",records).data("pages",teacherReadIPage.getPages()).data("total",teacherReadIPage.getTotal()).data("dictionary",dictionary);
    }

    /**
     * 条件查询
     * @param s
     * @return
     */
    @Override
    public R teacherConditionalQuery(String s,int current,int limit,String vipByJwtToken,String teacherIdByJwtToken) {
        Page<TeacherRead> teacherReadPage = new Page<TeacherRead>(current,limit);
        TeacherRead teacherRead = JSONObject.parseObject(s, TeacherRead.class);
        IPage<TeacherRead> teacherReadIPage = teacherMapper.teacherConditionalQuery(teacherReadPage, teacherRead,vipByJwtToken,teacherIdByJwtToken);
        List<TeacherRead> records = teacherReadIPage.getRecords();
        //获取字典表
        Map<String, List<Dictionary>> dictionary = this.getDictionary();
        return records.size() != 0 ? R.OK().data("list",records).data("dictionary",dictionary).data("total",teacherReadIPage.getTotal()).data("pages",teacherReadIPage.getPages()) : R.OK().message("您所查询的信息不存在").data("list",records).data("dictionary",dictionary).data("total",teacherReadIPage.getTotal()).data("pages",teacherReadIPage.getPages());
    }

    /**
     * 更新用户信息
     * @param s
     * @return
     */

    @Transactional
    @Override
    public R updateTeacherInfo(String s) {
        //Json转换
        TeacherRead teacherRead = JSONObject.parseObject(s, TeacherRead.class);
        Teacher teacher = new Teacher();
        TeacherEducation teacherEducation = new TeacherEducation();
        //复制属性
        BeanUtils.copyProperties(teacherRead,teacher);
        BeanUtils.copyProperties(teacherRead,teacherEducation);

        //构造条件
        QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.eq("id",teacher.getId());
        QueryWrapper<TeacherEducation> teacherEducationQueryWrapper = new QueryWrapper<TeacherEducation>();
        teacherEducationQueryWrapper.eq("id",teacherRead.getId());
        //返回数值1+1
        int teacherUpdate = teacherMapper.update(teacher, teacherQueryWrapper);
        int teacherEducationUpdate = teacherEducationMapper.update(teacherEducation, teacherEducationQueryWrapper);

        return (teacherUpdate + teacherEducationUpdate) == 2 ? R.OK().message(teacherRead.getTeacherId() + teacherRead.getName() + "修改成功") : R.ERROR().code(ResultCode.UPDATEERROR).message(teacherRead.getTeacherId() + teacherRead.getName() + "修改失败");
    }

    /**
     * 删除失败
     * @param id
     * @return
     */
    @Transactional
    @Override
    public R deleteTeacherById(String id) {
        int id1 = teacherMapper.delete(new QueryWrapper<Teacher>().eq("id", id));
        int id2 = teacherEducationMapper.delete(new QueryWrapper<TeacherEducation>().eq("id", id));
        return (id1 + id2) == 2 ? R.OK().message("删除成功") : R.ERROR().code(ResultCode.DELETEERROR).message("删除失败");
    }

    /**
     * 新增单个老师
     * @param teacherRead
     * @return
     */
    @Transactional
    @Override
    public R insertTeacherInfo(TeacherRead teacherRead) {
        Teacher teacher = new Teacher();
        TeacherEducation teacherEducation = new TeacherEducation();
        BeanUtils.copyProperties(teacherRead,teacher);
        BeanUtils.copyProperties(teacherRead,teacherEducation);
        int insert = 0;
        int insert2 = 0;
        try {
            insert = teacherMapper.insert(teacher);
            teacherEducation.setId(teacher.getId());
            insert2 = teacherEducationMapper.insert(teacherEducation);
        } catch (Exception e) {
            throw new YGException(ResultCode.UPDATEERROR,e.getCause().getMessage(),1);
        }
        return (insert + insert2) == 2 ? R.OK().message("新增教师成功") : R.ERROR().code(ResultCode.INSERTERROR).message(teacher.getId() + "数据库中已经存在");
    }


    /**
     * 查询字典表
     * @return
     */
    public Map<String, List<Dictionary>> getDictionary(){
        //查询
        List<Dictionary> title = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "title").orderByAsc("sort"));
        List<Dictionary> technical_positions = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "technical_positions").orderByAsc("sort"));
        List<Dictionary> education = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "education").orderByAsc("sort"));
        List<Dictionary> degree = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "degree").orderByAsc("sort"));
        List<Dictionary> postgraduate_type = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "postgraduate_type").orderByAsc("sort"));
        List<Dictionary> school_talent_level = dictionaryMapper.selectList(new QueryWrapper<Dictionary>().eq("english_name", "school_talent_level").orderByAsc("sort"));

        Map<String,List<Dictionary>> stringListMap = new HashMap<>();
        stringListMap.put("title",title);
        stringListMap.put("technical_positions",technical_positions);
        stringListMap.put("education",education);
        stringListMap.put("degree",degree);
        stringListMap.put("postgraduate_type",postgraduate_type);
        stringListMap.put("school_talent_level",school_talent_level);
        return stringListMap;
    }
}